package com.chensf.studydemo.common;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.util.AttributeSet;

import androidx.annotation.NonNull;

import com.chensf.studydemo.R;


public class ChatBubbleLayout extends ShapeLayout {

    private final float mTriangleSize;
    private final float mTriangleHeight;
    private final int mTriangleDirection;
    /**
     * 圆角半径
     */
    private float[] radiusArray = {0f, 0f, 0f, 0f, 0f, 0f, 0f, 0f};
    private RectF rectF = new RectF();
    private Drawable mForeground;

    public ChatBubbleLayout(Context context) {
        this(context, null);
    }

    public ChatBubbleLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public ChatBubbleLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        //读取气泡的圆角半径
        TypedArray a = context.getTheme().obtainStyledAttributes(attrs, R.styleable.ChatBubble, 0, 0);
        float bubbleRadius = a.getDimension(R.styleable.ChatBubble_bubbleRadius, 0);
        float contentPadding = a.getDimension(R.styleable.ChatBubble_contentPadding, 0);
        boolean needPadding = a.getBoolean(R.styleable.ChatBubble_needPadding, true);
        mTriangleSize = a.getDimension(R.styleable.ChatBubble_triangleSize, 16);
        mTriangleDirection = a.getInt(R.styleable.ChatBubble_triangleDirection, 0);
        Drawable foreground = a.getDrawable(R.styleable.ChatBubble_android_foreground);
        if (foreground != null) {
            setForeground(foreground);
        }
        a.recycle();
        mTriangleHeight = mTriangleSize * 3 / 4;
        if (needPadding) {
            if (mTriangleDirection == 0) {
                setPadding((int) (mTriangleSize + contentPadding), (int) mTriangleHeight, (int) contentPadding, (int) contentPadding);
            } else {
                setPadding((int) contentPadding, (int) mTriangleHeight, (int) (mTriangleSize + contentPadding), (int) contentPadding);
            }
        }
        setRadius(bubbleRadius);
    }

    @Override
    protected void drawPath(Path path, int srcWidth, int srcHeight, float scale, float translateX, float translateY) {
        //绘制路径
        path.reset();
        path.setFillType(Path.FillType.EVEN_ODD);
//        rectF.right = srcWidth;
//        rectF.bottom = srcHeight;
        if (mTriangleDirection == 0) {
            rectF.set(mTriangleSize, 0, srcWidth, srcHeight);
            path.addRoundRect(rectF, radiusArray, Path.Direction.CW);
            path.moveTo(0, 0);
            path.lineTo(mTriangleSize, 0);
            path.lineTo(mTriangleSize, mTriangleSize * 3 / 4);
        } else {
            rectF.set(0, 0, srcWidth - mTriangleSize, srcHeight);
            path.addRoundRect(rectF, radiusArray, Path.Direction.CW);
            path.moveTo(srcWidth, 0);
            path.lineTo(srcWidth - mTriangleSize, 0);
            path.lineTo(srcWidth - mTriangleSize, mTriangleSize * 3 / 4);
        }
    }

    /**
     * Supply a drawable resource that is to be rendered on top of all of the child
     * views in the frame layout.
     *
     * @param drawableResId The drawable resource to be drawn on top of the children.
     */
    public void setForegroundResource(int drawableResId) {
        setForeground(getContext().getResources().getDrawable(drawableResId));
    }

    /**
     * Supply a Drawable that is to be rendered on top of all of the child
     * views in the frame layout.
     *
     * @param drawable The Drawable to be drawn on top of the children.
     */
    @Override
    public void setForeground(Drawable drawable) {
        if (mForeground == drawable) {
            return;
        }
        if (mForeground != null) {
            mForeground.setCallback(null);
            unscheduleDrawable(mForeground);
        }

        mForeground = drawable;

        if (drawable != null) {
            drawable.setCallback(this);
            if (drawable.isStateful()) {
                drawable.setState(getDrawableState());
            }
        }
        requestLayout();
        invalidate();
    }

    @Override
    protected boolean verifyDrawable(@NonNull Drawable who) {
        return super.verifyDrawable(who) || who == mForeground;
    }

    @Override
    public void jumpDrawablesToCurrentState() {
        super.jumpDrawablesToCurrentState();
        if (mForeground != null) {
            mForeground.jumpToCurrentState();
        }
    }

    @Override
    protected void drawableStateChanged() {
        super.drawableStateChanged();
        if (mForeground != null && mForeground.isStateful()) {
            mForeground.setState(getDrawableState());
        }
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        if (mForeground != null) {
            mForeground.setBounds(0, 0, getMeasuredWidth(), getMeasuredHeight());
            invalidate();
        }
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        if (mForeground != null) {
            mForeground.setBounds(0, 0, w, h);
            invalidate();
        }
    }

    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        if (mForeground != null) {
            mForeground.draw(canvas);
        }
    }

    /**
     * 设置四个角的圆角半径
     */
    public void setRadius(float bubbleRadius) {
        radiusArray[0] = bubbleRadius;
        radiusArray[1] = bubbleRadius;
        radiusArray[2] = bubbleRadius;
        radiusArray[3] = bubbleRadius;
        radiusArray[4] = bubbleRadius;
        radiusArray[5] = bubbleRadius;
        radiusArray[6] = bubbleRadius;
        radiusArray[7] = bubbleRadius;
        if (mTriangleDirection == 0) {
            radiusArray[0] = 0;
            radiusArray[1] = 0;
        } else {
            radiusArray[2] = 0;
            radiusArray[3] = 0;
        }
        invalidate();
    }

}
